// 访问控制包
package accesscontroller

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"time"

	mgo "gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

// 访问控制类
type AccessController struct {
	session *mgo.Session
	dbName  string
}

const CollectionCustomers string = "customers"

// Token超期时间
const TokenExpire int64 = 24 * 60 * 60

// 构造函数
func NewAccessController(session *mgo.Session, dbName string) *AccessController {
	ac := AccessController{session: session, dbName: dbName}
	return &ac
}

// 创建Token字符串
func (p *AccessController) CreateToken(key string) string {
	i := time.Now().UnixNano()
	s := fmt.Sprintf("%d%s", i, key)

	md5Ctx := md5.New()
	md5Ctx.Write([]byte(s))
	cipherStr := md5Ctx.Sum(nil)
	token := hex.EncodeToString(cipherStr)

	return token
}

// 保存Token
func (p *AccessController) SaveToken(userId string, token string) {
	if !bson.IsObjectIdHex(userId) {
		return
	}

	s := p.session.Copy()
	defer s.Close()

	c := s.DB(p.dbName).C(CollectionCustomers)
	oid := bson.ObjectIdHex(userId)
	expire := time.Now().AddDate(0, 0, 1).Unix()
	c.Update(bson.M{"_id": oid}, bson.M{"$set": bson.M{"token": token, "tokenexpire": expire}})
}

type TokenT struct {
	Token       string `bson:"token"`
	TokenExpire int64  `bson:"tokenexpire"`
}

// 取出Token和过期时间
func (p *AccessController) GetToken(userId string) (token string, expire int64) {
	if !bson.IsObjectIdHex(userId) {
		return
	}

	s := p.session.Copy()
	defer s.Close()

	c := s.DB(p.dbName).C(CollectionCustomers)
	oid := bson.ObjectIdHex(userId)
	var res TokenT
	err := c.Find(bson.M{"_id": oid}).Select(bson.M{"_id": 0, "token": 1, "tokenexpire": 1}).One(&res)
	if err != nil {
		return
	}
	return res.Token, res.TokenExpire
}

// 检验Token
func (p *AccessController) Check(userId string, token string) bool {
	tk, exp := p.GetToken(userId)
	if token != tk {
		return false
	}
	if time.Now().Unix()-exp > TokenExpire {
		return false
	}
	return true
}
